package com.hospital.endescryption.module.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hospital.common.core.constants.InsuranceDeptEnum;
import com.hospital.common.core.constants.InsuranceFinal;
import com.hospital.common.core.constants.SqlFinalConstant;
import com.hospital.common.core.exception.ExceptionHelp;
import com.hospital.common.core.exception.ExceptionPrint;
import com.hospital.common.core.module.entity.MED.MedRequest;
import com.hospital.common.core.module.entity.NFC.NFCResponse;
import com.hospital.common.core.module.entity.NFC.ORG_RES;
import com.hospital.common.core.result.ErrorTip;
import com.hospital.common.core.result.SuccessTip;
import com.hospital.common.core.result.Tip;
import com.hospital.common.core.utils.CollectionKit;
import com.hospital.common.core.utils.HseEncAndDecUtil;
import com.hospital.common.core.utils.Sm2Demo;
import com.hospital.common.core.utils.Sm3Demo;
import com.hospital.endescryption.async.WxPayFunc;
import com.hospital.endescryption.config.properties.InsurProperties;
import com.hospital.endescryption.module.entity.EncryptionDecryptionDict;
import com.hospital.endescryption.module.service.EncryptionDecryptionDictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/enctrytion")
public class enctrytionController {
    @Resource
    private InsurProperties insurProperties;
    @Resource
    private WxPayFunc wxPayFunc;

    @Resource
    private EncryptionDecryptionDictService  encryptionDecryptionDictService;

    /**
     * 支付宝及人保入参加密接口，HIS调用医保接口的入参加密
     *
     * @param requestVal
     * @param request
     * @return
     */
    @PostMapping(value = "/insurance", produces = {"application/json;charset=UTF-8"})
    public String getorgone(@RequestBody NFCResponse requestVal, HttpServletRequest request) {
        ORG_RES tip = null;
        String descryption = null;
        String encryption = null;
        //第一层参数校验
        try {
            tip = wxPayFunc.validateFunc(requestVal);
        } catch (ExceptionHelp e) {
            tip = new ORG_RES(InsuranceDeptEnum.HOS_ERROR, e.getMessage());
        } catch (Exception e) {
            tip = new ORG_RES(InsuranceDeptEnum.FILED_REQ_BILL_SERVER, e.getMessage());
        } finally {

            Map<String, String> map = new HashMap<>();
            long timeInMillis = Calendar.getInstance().getTimeInMillis();
            try {
                EncryptionDecryptionDict encryptionDecryptionDict = null;
                if (JSON.toJSONString(requestVal).contains("channel")) {
                    encryptionDecryptionDict =getBySql(InsuranceFinal.ENC,requestVal.getChannel(),requestVal.getFromApp(),requestVal.getToApp());
                } else {
                    encryptionDecryptionDict = new EncryptionDecryptionDict();
                    encryptionDecryptionDict.setAppId(insurProperties.getAppIdHis());
                    encryptionDecryptionDict.setAppSecret(insurProperties.getAppSecretHis());
                }
                if (requestVal.getSignType().equals(insurProperties.getSingTypeHis())) {
                    NFCResponse nfcResponse = new NFCResponse();
                    nfcResponse.setSignType(insurProperties.getSingTypeHis());
                    nfcResponse.setEncType(insurProperties.getEncryptType());
                    nfcResponse.setVersion(insurProperties.getVersion());
                    nfcResponse.setCode(0);
                    nfcResponse.setAppId(insurProperties.getAppIdInsur());
                    nfcResponse.setTimestamp(String.valueOf(timeInMillis));
                    nfcResponse.setData(requestVal.getData());

                    map = Sm2Demo.encAndSingRes(JSON.toJSONString(requestVal.getData()), JSON.parseObject(JSON.toJSONString(nfcResponse)), encryptionDecryptionDict.getAppId(),
                            encryptionDecryptionDict.getAppSecret(), encryptionDecryptionDict.getHosPublicKey(), encryptionDecryptionDict.getHosPrivateKey());
                    nfcResponse.setEncData(map.get(InsuranceFinal.ENCRYPT_DATA));
                    nfcResponse.setSignData(map.get(InsuranceFinal.SIGN_DATA));
                    nfcResponse.setMessage(tip.getRet_msg());
                    encryption = JSON.toJSONString(nfcResponse);
                } else {
                    encryption = getRequest(requestVal.getData(), encryptionDecryptionDict.getAppId(), encryptionDecryptionDict.getAppSecret());
                }
            } catch (Exception e) {
                tip = new ORG_RES(InsuranceDeptEnum.FILED_REQ_BILL_SERVER, e.getMessage());
            } finally {
                ExceptionPrint.printCommErrorString("加密接口",
                        JSON.toJSONString(requestVal),
                        String.valueOf(tip.getRet_code())
                        , tip.getRet_msg(), "", "返回给接口加密数据：" + encryption, descryption, "", "");
            }
        }
        return encryption;
    }

    /**
     * 微信及电子处方上传加密接口
     *
     * @param requestVal
     * @return
     */
    @PostMapping(value = "/insurWeChatPresc", produces = {"application/json;charset=UTF-8"})
    public Tip getorgone(@RequestBody NFCResponse requestVal) {
        Tip tip = null;
        EncryptionDecryptionDict encryptionDecryptionDict =getBySql(InsuranceFinal.ENC,requestVal.getChannel(),requestVal.getFromApp(),requestVal.getToApp());
        JSONObject jsonObject = null;
        try {
            Object data = requestVal.getData();
            String parse = JSON.toJSONString(data);
            jsonObject = HseEncAndDecUtil.encryptMsg(encryptionDecryptionDict.getAppId(),
                    encryptionDecryptionDict.getAppSecret(), encryptionDecryptionDict.getHosPrivateKey(), "", JSON.parseObject(parse));
            tip = new SuccessTip();
            tip.setData(jsonObject);
        } catch (Exception e) {
            tip = new ErrorTip(303, e.getMessage());
        } finally {
            ExceptionPrint.printCommErrorString("加密接口",
                    JSON.toJSONString(requestVal),
                    String.valueOf(tip.getCode())
                    , tip.getMessage(), "", "返回给接口加密数据：" + jsonObject, "", "", "");
        }
        return tip;
    }

    /**
     * 获取最终的接口调用类
     *
     * @return
     */
    private String getRequest(Object data, String appId, String appSecret) {
        MedRequest medRequest = new MedRequest();
        BeanUtils.copyProperties(insurProperties, medRequest);
        long timeInMillis = Calendar.getInstance().getTimeInMillis();
        medRequest.setTimestamp(String.valueOf(timeInMillis));
        medRequest.setSignType(insurProperties.getSignType());
        medRequest.setVersion(insurProperties.getVersion());
        medRequest.setAppId(appId);
        String jsonString = JSON.toJSONString(data);
        Object parse = JSON.parse(jsonString);
        JSONObject jsonObject = JSON.parseObject(parse.toString());
        medRequest.setParam(jsonObject);
        Map<String, String> map = Sm3Demo.encAndSingHis(jsonObject.toString(), JSON.parseObject(JSON.toJSONString(medRequest)), appId, appSecret);
        medRequest.setEncryptData(map.get(InsuranceFinal.ENCRYPT_DATA));
        medRequest.setSign(map.get(InsuranceFinal.SIGN_DATA));
        medRequest.setParam(null);
        medRequest.setCode(0);
        return JSON.toJSONString(medRequest);
    }

    public EncryptionDecryptionDict getBySql(String dateType,String channel,String fromApp,String fromTo){
        List<EncryptionDecryptionDict> list = encryptionDecryptionDictService.list(new QueryWrapper<EncryptionDecryptionDict>().apply(SqlFinalConstant.ENDEC_SQL, dateType,
                channel, fromApp, fromTo));
        if (CollectionKit.isNotEmpty(list)){
            return list.get(0);
        }
        return null;
    }

}
